/* Copyright (C) 2007-2008  klevgert  http://code.google.com/p/db4o-netbeans/

This file is part of the db4o-netbeans module suite.

db4o-netbeans is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation.
 
db4o-netbeans is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */

package com.db4o.nb.wizards;

import com.db4o.nb.api.Db4oProvider;
import com.db4o.nb.util.DialogUtil;
import java.awt.Component;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.swing.JComponent;
import javax.swing.event.ChangeListener;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.spi.project.ui.templates.support.Templates;
import org.openide.NotifyDescriptor;
import org.openide.WizardDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;

/**
 * Wizard to create a new Java file.
 * @author klevgert
 */
public class Db4oTemplateIterator implements WizardDescriptor.InstantiatingIterator {
    
    //private static ResourceBundle bundle = NbBundle.getBundle(Db4oTemplateIterator.class);

  private static final long serialVersionUID = 1L;

  private transient int index;
  private transient WizardDescriptor.Panel[] panels;
  private transient WizardDescriptor wiz;

  /** Create a new wizard iterator. */
  public Db4oTemplateIterator() {}

  private WizardDescriptor.Panel[] createPanels (WizardDescriptor wizardDescriptor) {

      // Ask for Java folders
      Project project = Templates.getProject( wizardDescriptor );
      Sources sources = ProjectUtils.getSources(project);

      return new WizardDescriptor.Panel[] {            
          Templates.createSimpleTargetChooser( project, new SourceGroup[] {}),
          new Db4oTemplatePanel()
      };
  }

  private String[] createSteps(String[] before, WizardDescriptor.Panel[] panels) {
      assert panels != null;
      // hack to use the steps set before this panel processed
      int diff = 0;
      if (before == null) {
          before = new String[0];
      } else if (before.length > 0) {
          diff = ("...".equals (before[before.length - 1])) ? 1 : 0; // NOI18N
      }
      String[] res = new String[ (before.length - diff) + panels.length];
      for (int i = 0; i < res.length; i++) {
          if (i < (before.length - diff)) {
              res[i] = before[i];
          } else {
              res[i] = panels[i - before.length + diff].getComponent ().getName ();
          }
      }
      return res;
  }

  public Set/*<FileObject>*/ instantiate () throws IOException {

      // Create the new file.
      FileObject dir = Templates.getTargetFolder( wiz );
      String targetName = Templates.getTargetName( wiz );

      DataFolder df = DataFolder.findFolder( dir );
      FileObject template = Templates.getTemplate( wiz );

      FileObject createdFile = null;
      DataObject dTemplate = DataObject.find( template );                
      DataObject dobj = dTemplate.createFromTemplate( df, targetName );
      createdFile = dobj.getPrimaryFile();

      // Setup db4o template data
      Db4oProvider provider = (Db4oProvider) dobj.getCookie(Db4oProvider.class);
      if( provider != null ) {

        Db4oTemplatePanel pnl = (Db4oTemplatePanel) this.panels[1];
        Db4oTemplateComponent cmp = (Db4oTemplateComponent)pnl.getComponent();

        provider.getDatabase().setName( targetName );
        if( cmp.getCmbConnectionType().getSelectedItem().equals("File") ) {

          String file = cmp.getTxtFilename().getText();
          provider.getDatabase().setFile( file );

        } else if( cmp.getCmbConnectionType().getSelectedItem().equals("Server") ) {

          provider.getDatabase().setHost( cmp.getTxtHost().getText() );
          provider.getDatabase().setPort( cmp.getTxtPort().getText() );
          provider.getDatabase().setUser( cmp.getTxtUser().getText() );

          StringBuilder sb = new StringBuilder();
          sb.append( cmp.getTxtPassword().getPassword() );
          provider.getDatabase().setPassword( sb.toString() );

        }
        provider.save();
      }

      return Collections.singleton( createdFile );
  }

//  private String confirmCreationIfNotExists(final FileObject dir, String file) 
//    throws IOException {
//    
//    File f = new File( file );
//    if( !f.exists() ) {
//      
//      String message = "File does not exist yet.\n" +
//          "Should it be created now in the same directory?\n\n" +
//          "";
//      if( DialogUtil.confirmYesNo(message).equals(DialogUtil.YES) ) {
//        
//        FileObject fileObj = FileUtil.createData(dir,file);
//        file = fileObj.getPath();
//      
//      }
//    }
//    return file;
//  }
    
  public void initialize(WizardDescriptor wiz) {
      this.wiz = wiz;
      index = 0;
      panels = createPanels( wiz );

      // Make sure list of steps is accurate.
      String[] beforeSteps = null;
      Object prop = wiz.getProperty ("WizardPanel_contentData"); // NOI18N
      if (prop != null && prop instanceof String[]) {
          beforeSteps = (String[])prop;
      }
      String[] steps = createSteps (beforeSteps, panels);
      for (int i = 0; i < panels.length; i++) {
          Component c = panels[i].getComponent();
          if (steps[i] == null) {
              // Default step name to component name of panel.
              // Mainly useful for getting the name of the target
              // chooser to appear in the list of steps.
              steps[i] = c.getName();
          }
          if (c instanceof JComponent) { // assume Swing components
              JComponent jc = (JComponent)c;
              // Step #.
              jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i)); // NOI18N
              // Step name (actually the whole list for reference).
              jc.putClientProperty("WizardPanel_contentData", steps); // NOI18N
          }
      }
  }
  public void uninitialize (WizardDescriptor wiz) {
      this.wiz = null;
      panels = null;
  }

  public String name() {
      //return "" + (index + 1) + " of " + panels.length;
      return ""; // NOI18N
  }

  public boolean hasNext() {
      return index < panels.length - 1;
  }
  public boolean hasPrevious() {
      return index > 0;
  }
  public void nextPanel() {
      if (!hasNext()) throw new NoSuchElementException();
      index++;
  }
  public void previousPanel() {
      if (!hasPrevious()) throw new NoSuchElementException();
      index--;
  }
  public WizardDescriptor.Panel current() {
      return panels[index];
  }

  private transient Set listeners = new HashSet(1);

  public final void addChangeListener(ChangeListener l) {
      synchronized(listeners) {
          listeners.add(l);
      }
  }
  public final void removeChangeListener(ChangeListener l) {
      synchronized(listeners) {
          listeners.remove(l);
      }
  }
  protected final void fireChangeEvent() {
//        ChangeListener[] ls;
//        synchronized (listeners) {
//            ls = listeners.toArray(new ChangeListener[listeners.size()]);
//        }
//        ChangeEvent ev = new ChangeEvent(this);

//        for (ChangeListener l : ls) {
//            l.stateChanged(ev);
//        }
  }

    
}